![]() | |
|
|
|
To access the contents, click the chapter and section titles.
Bug Proofing Visual Basic: A Guide to Error Handling and Prevention
Also consider recent changes to the operating system and other software you may have just upgraded. You may not be able to change the behavior of the system, but knowing what changed may help you determine the parts of your program that you need to examine. For example, if you have recently upgraded a custom control, look for places where the program uses the controls properties, events, and methods. Think about data that may have changed. Even if the code has not changed, if the data manipulated by the code changes, it may make bugs appear. The apparent bugs may be correct behavior that you do not recognize because you have not used the new data before. They may also be real bugs that did not surface with the previous data. Finally, consider the possibility that the bug was always there and that you simply failed to notice it before. Sometimes when you notice a bug, it seems so obvious that you wonder how it could ever have escaped detection. Dont Believe in MagicJust as bugs do not spontaneously appear, they do not spontaneously fix themselves. If a bug seems to have disappeared, it is almost surely still there, but hiding. Remember that you will eventually need to find and fix every bug. Assuming a bug fixed itself will just make it harder to find later. Continue chasing the bug while it is fresh in your mind. Do not stop until you find the bug, even if it appears to have gone away by itself. Once in a great while, fixing one bug also fixes another. While working through your list of bugs, one may disappear. Do not assume a previous bug fix has removed this bug unless you can prove it. It is just as likely that another bug fix hid the bug rather than removing it. Study the modified code until you figure out how the previous change removed the bug. Add a new comment explaining how the other repair worked its magic. Fix Routines, Not LinesDo not use the debugger to pinpoint the single line that caused a bug and fix it. Instead, study the entire routine so you understand what it is supposed to do and what it actually does. Unless you understand the context in which the bug appears, you cannot safely fix it. It is also possible that the bug involves more than one line of code. Looking for a single incorrect line can distract you from finding the whole problem. Note that understanding the entire routine means it will be easier to debug short routines. It is also easier to debug a routine that performs one well-defined task instead of one that performs several poorly described unrelated tasks. It is easier to keep the entire purpose of a short, well-focused routine in mind all at once. Make debugging easier by keeping that in mind when you program. Keep routines tightly focused on the task at hand so they are easier to fix later. Fix Bugs, Not SymptomsBe sure you have uncovered the true bug before you modify the source code. Sometimes one routine will fail because of a condition caused by another routine. If the other routine is wrong, the condition is a symptom of a bug in that other routine. Fix the real bug. Do not simply modify the first routine so it can recover when the erroneous condition occurs. It is not always obvious whether a particular routines behavior is its own fault or the fault of an auxiliary routine. In that case, ask yourself whether other routines will also be confused by the results of the auxiliary routine. If so, you should rewrite that routine so it makes sense to all of the routines instead of merely covering up the problem in this one instance. For example, suppose the NumNonBlanks function returns the number of nonblank characters selected in a text box and the NumWords function returns the number of words selected. The following function uses those two functions to calculate the average length of the selected words.
Private Function AverageWordLength() As Single
AverageWordLength = NumNonBlanks / NumWords
End Function
Now suppose you test the program and trace a bug to this function. The AverageWordLength function crashes when no words are selected in the text box and NumWords is 0. In this example, you should ask yourself if the bug is in AverageWordLength or in the NumWords function. If the bug is in NumWords, other routines may be confused by its behavior. In this case, NumWords is returning a sensible value. When no words are selected, it makes sense to return the value 0. If NumWords is not at fault, the bug must be in the AverageWordLength function. For another example, suppose the BestStudent function returns the index of the student who received the highest score on a test if any student received a score greater than 90. If no student scored more than 90, the routine returns 1 indicating that no student deserves special honors. Now suppose another routine displays the names of the highest-scoring students for each test using the following code:
For test_num = 1 To NumTests
lblHonorsStudent(test_num).Caption = _
StudentNames(BestStudent(test_num))
Next test_num
This code fails if there is some test for which no student scored better than 90. In that case, BestStudent returns 1 and the routine fails trying to access the 1 entry in the StudentNames array. For this code, you should ask whether the bug is in this display routine or in the BestStudent function. In this case, the BestStudent function returns a misleading result. It does not return the index of the best student. Instead, it returns the index of the student most deserving of honors but only if some student scored high enough to deserve honors. The display routine is not really the source of the error. Any other routine that uses BestStudent can suffer from the same confusion. The problem is in BestStudent, not in the display routine. There are two good ways to fix this bug. First, you can make BestStudent return the index of the best student even if that student did not do very well. If the best student scores a 50, he is still the best student. The meaning of the function matches its name. Second, you could change the name of BestStudent to HonorsStudent so it correctly reflects the functions return value. Note that both of these fixes could cause problems in other parts of the program. Another routine that uses BestStudent may already be using special code to protect itself from the value 1. Changing BestStudent so it always returns a valid index may make that code fail. This underscores the importance of fixing the real bug and not the symptom. If the programmer writing that other routine had fixed BestStudent instead of patching the other routine to accommodate the 1 value, this problem would never have arisen. Similarly, if another routine relies on the fact that BestStudent never returns the index of a student with a score less than 90, it may break when you fix BestStudent. This emphasizes the importance of finding and fixing errors as early as possible. If BestStudent had been fixed before the other routine was written, it would have relied on the correct behavior and there would have been no problem.
|
|
Products | Contact Us | About Us | Privacy | Ad Info | Home
Use of this site is subject to certain Terms & Conditions, Copyright © 1996-1999 EarthWeb Inc. All rights reserved. Reproduction whole or in part in any form or medium without express written permision of EarthWeb is prohibited.
|